// 2025/10/11: 首个版本

using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using CommunityToolkit.Mvvm.ComponentModel;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using Avalonia.Media.Imaging;
using ASEva;
using ASEva.UIAvalonia;
using ASEva.Utility;

namespace CommonSource
{
    partial class DataPath : DialogPanel
    {
        public DataPath() // For designer
        {
            InitializeComponent();
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());
        }

        public class IconResourceNames
        {
            public String DialogIcon { get; set; } // .ico
            public String ConfigIcon { get; set; } // .png
            public String AddIcon { get; set; } // .png
            public String DeleteIcon { get; set; } // .png
            public String MatrixIcon { get; set; } // .png
            public String OpenFolderIcon { get; set; } // .png
        }

        public DataPath(object caller, IconResourceNames iconResourceNames)
        {
            InitializeComponent();
            SetFixMode(600, 80, true);
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());
            Icon = ResourceLoader.Load(iconResourceNames?.DialogIcon)?.ToAvaloniaWindowIcon();
            Title = language["title"];
            DataContext = new Model(iconResourceNames ?? new());

            IsEnabled = false;
            buttonOpenFolder.IsVisible = !AgencyLocal.ClientSide;
            updateDataPathAndWaitToUpdateLayers();

            buttonConfig.Click += async delegate
            {
                IsEnabled = false;
                if (AgencyLocal.ClientSide)
                {
                    await AgencyAsync.RunConsole(caller, "config-data-path.consoleworkflow");
                }
                else
                {
                    var results = await this.GetStorageProvider().OpenFolderPickerAsync(new FolderPickerOpenOptions());
                    if (results.Count == 1) AgencyLocal.SetDataPath(results[0].Path.LocalPath);
                }
                updateDataPathAndWaitToUpdateLayers();
            };

            buttonAdd.Click += async delegate
            {
                var dialog = new InputNumberOrString(language["add-layer"], null, iconResourceNames?.DialogIcon);
                await App.RunDialog(dialog);
                if (String.IsNullOrWhiteSpace(dialog.InputValue)) return;

                IsEnabled = false;
                await AgencyAsync.AddDataLayer(dialog.InputValue);
                await AgencyAsync.SetCurrentDataLayer(dialog.InputValue);
                await updateLayers();
                IsEnabled = true;
            };

            buttonDelete.Click += async delegate
            {
                IsEnabled = false;
                await AgencyAsync.DeleteDataLayer((comboBox.SelectedItem as Item).ID);
                await updateLayers();
                IsEnabled = true;
            };

            comboBox.SelectionChanged += async delegate
            {
                if (!IsEnabled) return;
                if (comboBox.SelectedItem == null)
                {
                    buttonDelete.IsEnabled = false;
                }
                else
                {
                    var target = (comboBox.SelectedItem as Item).ID;
                    await AgencyAsync.SetCurrentDataLayer(target);
                    buttonDelete.IsEnabled = !(String.IsNullOrEmpty(target) || target == "." || target == "..");
                }
            };

            buttonMatrix.Click += async delegate
            {
                await App.RunDialog(new SessionGenerationMatrix{ IconResourceName = iconResourceNames?.DialogIcon });
            };

            buttonOpenFolder.Click += async delegate
            {
                var dataPath = await AgencyAsync.GetGlobalParameter("System.DataPath", null);
                var currentLayer = await AgencyAsync.GetCurrentDataLayer();

                var targetPath = dataPath;
                if (!(String.IsNullOrEmpty(currentLayer) || currentLayer == "." || currentLayer == "..")) targetPath = Path.Combine(dataPath, currentLayer);

                if (!String.IsNullOrEmpty(targetPath) && Directory.Exists(targetPath))
                {
                    AgencyLocal.StartProcess(targetPath);
                }
            };
        }

        private async void updateDataPathAndWaitToUpdateLayers()
        {
            var dataPath = await AgencyAsync.GetGlobalParameter("System.DataPath", null);
            labelDataPath.Content = String.IsNullOrEmpty(dataPath) || dataPath == "na" ? "---" : dataPath;
            buttonOpenFolder.IsEnabled = !String.IsNullOrEmpty(dataPath) && Directory.Exists(dataPath);

            while (true)
            {
                await Task.Delay(10);
                if ((await AgencyAsync.IsReady()).Item1) break;
            }

            await updateLayers();
            IsEnabled = true;
        }

        private async Task updateLayers()
        {
            Task[] tasks = [ AgencyAsync.GetDataLayers(), AgencyAsync.GetCurrentDataLayer(), AgencyAsync.GetAppMode() ];
            await Task.WhenAll(tasks);

            var layers = (tasks[0] as Task<String[]>).Result;
            var currentLayer = (tasks[1] as Task<String>).Result ?? "";
            var appMode = (tasks[2] as Task<ApplicationMode>).Result;

            var items = new List<Item>();
            Item selectedItem = null;
            bool rootAsSession = false;
            bool selectSpecialLayer = false;
            if (layers != null)
            {
                items.Add(new Item{ ID = "", Title = language["layer-all"] });
                if (currentLayer == "")
                {
                    selectedItem = items.Last();
                    selectSpecialLayer = true;
                }

                foreach (var id in layers)
                {
                    if (id == ".")
                    {
                        items.Add(new Item{ ID = id, Title = language["layer-under"] });
                        if (id == currentLayer)
                        {
                            selectedItem = items.Last();
                            selectSpecialLayer = true;
                        }
                    }
                    else if (id == "..")
                    {
                        items.Add(new Item{ ID = id, Title = language["layer-as"] });
                        rootAsSession = true;
                        if (id == currentLayer)
                        {
                            selectedItem = items.Last();
                            selectSpecialLayer = true;
                        }
                    }
                    else
                    {
                        items.Add(new Item{ ID = id, Title = id });
                        if (id == currentLayer) selectedItem = items.Last();
                    }
                }
            }
            comboBox.ItemsSource = items;
            if (selectedItem != null) comboBox.SelectedItem = selectedItem;
            comboBox.IsEnabled = items.Count > 0;
            buttonAdd.IsEnabled = items.Count > 0 && !rootAsSession;
            buttonDelete.IsEnabled = items.Count > 0 && !selectSpecialLayer;
            buttonMatrix.IsEnabled = items.Count > 0 && (appMode == ApplicationMode.Offline || appMode == ApplicationMode.Replay);
        }

        private class Item
        {
            public String ID { get; set; }
            public String Title { get; set; }
            public override string ToString()
            {
                return Title;
            }
        }

        private partial class Model(IconResourceNames names) : ObservableObject
        {
            [ObservableProperty]
            private Bitmap configIcon = ResourceLoader.Load(names.ConfigIcon).ToAvaloniaBitmap();

            [ObservableProperty]
            private Bitmap addIcon = ResourceLoader.Load(names.AddIcon).ToAvaloniaBitmap();

            [ObservableProperty]
            private Bitmap deleteIcon = ResourceLoader.Load(names.DeleteIcon).ToAvaloniaBitmap();

            [ObservableProperty]
            private Bitmap matrixIcon = ResourceLoader.Load(names.MatrixIcon).ToAvaloniaBitmap();

            [ObservableProperty]
            private Bitmap openFolderIcon = ResourceLoader.Load(names.OpenFolderIcon).ToAvaloniaBitmap();
        }

        private LanguageSwitch language;
    }
}